import ScriptManager from '../Tools/ScriptManager';
import GameManager from './GameManager';
import Character from './Basis/Character';


const { ccclass, property } = cc._decorator;

type AutoPathGridGrid={
    point:cc.Vec2
    G:number
    H:number
    F:number,
    parent?:AutoPathGridGrid
}

@ccclass
export default class MapTerrain extends cc.Component {    
    private tileSize:{x?:number,y?:number} = {}
    private tilePx:{x?:number,y?:number} = {}
    /**
     *  地型数组
     *  1 不可行走
     *  0 可行走
     *  其他未定义
     */
    private terrain:number[] =[];
    private mapSize:cc.Vec2;
    private _debug:boolean;
    set debug(value){
        if(this.debug==value)return;
        this._debug = value;
        this.debugTerrain();
        //this.debugTerrain1();
    }
    get debug(){
        return this._debug;
    }

    private tempPlayer:Character;

    onLoad(){        
        if(ScriptManager.Instance.MapTerrain)return;

        let size = this.node.getContentSize()
        this.mapSize = cc.v2(size.width,size.height);
        ScriptManager.Instance.MapTerrain = this;  
        
        
        
        let name = cc.director.getScene().name        
        let jsonAsset = cc.loader.getRes("Terrain/"+name,cc.JsonAsset);
        
        for(let k in jsonAsset.json){
           this[k] = jsonAsset.json[k];
        }
        this.debug = true;   
    }

    start(){
        //初始化地图中的一些建筑物品的Zindex        
        for(let i=0;i<this.node.children.length;i++){
            let item = this.node.children[i];
            item.setSiblingIndex(this.mapSize.y/2+item.y);
        }
    }

    /**
     * 测试自动寻路
     * @param event 
     */
    testAutoFindPath(event:cc.Event.EventTouch){
        if(!this.tempPlayer){
            this.tempPlayer = this.node.getComponentInChildren(Character)                        
        }        
        //获取点击点
        let p1 = event.getLocation()                       
        //点击点转换到世界坐标系
        p1 = cc.Camera.main.getCameraToWorldPoint(p1,null);
        //世界坐标系转到Map节点坐标系下
        p1 =this.node.convertToNodeSpaceAR (p1)                    
                
        this.tempPlayer.AutoMove(p1)
        return;        
    }

    /** 检测地地型是否可移动 */
    checkMove(p:cc.Vec2){
        let p1 = this.getTileV2(p);

        let index = p1.x+p1.y*this.tileSize.x;        
        switch(this.terrain[index]){
            case 1:
                return false;
            break;
        }        
        return true;
    }

    /**
     * 将坐标点转换成tile坐标
     */
    getTileV2(p:cc.Vec2){
        //地图是以0.5 0.5为锚点,计算坐标时地图也要以0.5计算        
        let p1 = this.mapSize.mul(0.5,null);
        //地型是以左上角为起点，而p是以左下角为起点,统一坐标为地型的左上角计算     
        let p2 = cc.v2(p1.x+p.x, p1.y-p.y);

        //限定p2的范围 防止出界
        let p3 = p2.clampf(cc.Vec2.ZERO,this.mapSize);
        
        //计算坐标所在地型的Index
        let x = Math.floor(p3.x/this.tilePx.x);
        let y = Math.floor(p3.y/this.tilePx.y);
        return cc.v2(x,y);
    }

    /**
     * 将图块坐标转成index
     */
    getIndexTileV2(t2:cc.Vec2){
        let index = t2.x+t2.y*this.tileSize.x;
        return index;
    }
    /**
     * 将图块坐标转换成点坐标
     */
    getPointTileV2(t2:cc.Vec2){
        let p = cc.v2(t2.x*this.tilePx.x, (this.tileSize.y- t2.y)*this.tilePx.y); 
        return cc.v2( p.x-this.node.width/2,p.y-this.node.height/2-this.tilePx.y/2  )
    }

    /** 地形Debug */
    debugTerrain(){
        if(!this.debug){
            let node = this.node.getChildByName("debug");
            if(node){
                node.removeFromParent();
            }
            return;
        }

        let node = new cc.Node;
        node.name = "debug"
        let graphics = node.addComponent(cc.Graphics);
        node.setContentSize(this.mapSize.x,this.mapSize.y);
        node.setParent(this.node);
        //先绘画前十个矩形
        //第一个的坐标
        for(let index=0;index<this.terrain.length;index++){
            if(this.terrain[index]==1){
                let x =  index%this.tileSize.x
                let y = Math.floor(index/this.tileSize.x);      
                let p1 = cc.v2(x*this.tilePx.x,y*this.tilePx.y);
                let p2 = this.mapSize.mul(0.5);                
                let p3 = cc.v2(p1.x-p2.x,p2.y-p1.y-this.tilePx.y);                
                graphics.rect(p3.x,p3.y,this.tilePx.x,this.tilePx.y);                
            }
        }     
        graphics.fillColor = cc.color(255,0,0,50);
        graphics.fill();
        graphics.strokeColor = cc.color(0,0,0);        
        graphics.stroke();        

    }

    debugTerrain1(){
        if(!this.debug){
            let node = this.node.getChildByName("debug1");
            if(node){
                node.removeFromParent();
            }
            return;
        }

        let node = new cc.Node;
        node.name = "debug1"
        let graphics = node.addComponent(cc.Graphics);
        node.setContentSize(this.mapSize.x,this.mapSize.y);
        node.setParent(this.node);
        //先绘画前十个矩形
        //第一个的坐标
        for(let index=0;index<this.terrain.length;index++){
            if(this.terrain[index]===0){
                let x =  index%this.tileSize.x
                let y = Math.floor(index/this.tileSize.x);      
                let p1 = cc.v2(x*this.tilePx.x,y*this.tilePx.y);
                let p2 = this.mapSize.mul(0.5);                
                let p3 = cc.v2(p1.x-p2.x,p2.y-p1.y-this.tilePx.y);                
                graphics.rect(p3.x,p3.y,this.tilePx.x,this.tilePx.y);                
            }
        }          
        graphics.fillColor = cc.color(0,255,0,50);
        graphics.fill();
        graphics.strokeColor = cc.color(0,0,255);        
        graphics.stroke();        
    }

   
    /** 自动寻路 
     * t0 起始点
     * t1 终点
     * G 从起点到当前方块的移动量
     * H 从当前点到目标的移动量
     * F G+H     
    */
    AutoFindPath(p0:cc.Vec2,p1:cc.Vec2){    
        cc.log(p0,p1);
        //将目标坐标点转换成tile坐标
        let t0 = this.getTileV2(p0) 
        let t1 = this.getTileV2(p1)



        let closed:AutoPathGridGrid[]= [];
        let open:AutoPathGridGrid[]=[];

        //计算G 当前点C  Math.abs(c.x-t0.x) + Math.abs(c.y-t0.y);
        //计算H 当前点C  Math.abs(c.x-t1.x) + Math.abs(c.y-t1.y);
        let g0:AutoPathGridGrid = {
            point:t0,
            G:0,
            H:Math.abs(t0.x-t1.x) + Math.abs(t0.y-t1.y),
            F:Math.abs(t0.x-t1.x) + Math.abs(t0.y-t1.y),
            parent:null
        }
        let dirs =  [
            cc.v2(0,1),
            cc.v2(1,0),
            cc.v2(0,-1),
            cc.v2(-1,0)
        ]
        open.push(g0);
        
        
        let loop = true;
        let tempIndex=20000;
        let endGrid:AutoPathGridGrid;

        while(loop && tempIndex--){
            
            open.sort((a,b)=>{return a.F-b.F})
            
            //当前格子
            let CG = open.shift();            
            
            if(CG.point.equals(t1)){
                loop = false;
                cc.log("查找到终点")
                endGrid = CG;
                break;
            }
            
            closed.push(CG)
            for(let i=0;i<dirs.length;i++){
                let tp = CG.point.add(dirs[i]);
                if(this.terrain[this.getIndexTileV2(tp)]==1 || closed.findIndex(item=>{return item.point.equals(tp)})>-1 ){

                }else{
                    let tg = Math.abs(tp.x-t0.x) + Math.abs(tp.y-t0.y);
                    let th = Math.abs(tp.x-t1.x) + Math.abs(tp.y-t1.y);
                    let tf = tg+th;
    
                    let TG:AutoPathGridGrid={
                        point:tp,
                        G:tg,
                        H:th,
                        F:tf,
                        parent:CG
                    }
                    
                    let index = open.findIndex(item=>{return item.point.equals(tp)})                    
                    if( index==-1 ){                        
                        open.push(TG)
                    }else{
                        if(TG.F<open[index].F){
                            open[index] = TG
                        }
                    }
                }
            }
        }

        let paths:cc.Vec2[] = [];
        while(endGrid.parent){
            //cc.log(endGrid.point)
            paths.push(
                this.getPointTileV2(endGrid.point)
            )
            endGrid = endGrid.parent    
        }


        return paths.reverse();
    }

  
}



